package year2022.redis;

import org.apache.storm.shade.org.apache.commons.lang.StringUtils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

public class RedisNioClient {
    private static String CRLF="\r\n";

    public static void main(String[] args) throws Exception {
        client();
    }

    private static void client() {
        SocketChannel socketChannel = null;
        try {
            socketChannel = SocketChannel.open();
            socketChannel.configureBlocking(false);
            socketChannel.connect(new InetSocketAddress("127.0.0.1",6379));
            while(!socketChannel.finishConnect()){
                System.out.println("wait for connect ...");
            }

            String auth = buildRdsTcp(new String[]{"AUTH", "caijin_dev"});
            request(socketChannel, auth);
            System.out.println("auth response：\n" + response(socketChannel));

            String set = buildRdsTcp(new String[]{"set", "key1", "666"});
            request(socketChannel, set);
            System.out.println("set response：\n" + response(socketChannel));

            String get = buildRdsTcp(new String[]{"get", "key1"});
            request(socketChannel, get);
            System.out.println("get response：\n" + response(socketChannel));
        } catch (IOException e){
            e.printStackTrace();
        } finally {
            try {
                socketChannel.shutdownOutput();
                socketChannel.shutdownInput();
                socketChannel.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static String buildRdsTcp(String[] valArr){
        if (valArr==null || valArr.length==0){
            return "";
        }

        StringBuffer strBuild = new StringBuffer();
        strBuild.append("*").append(valArr.length).append(CRLF);

        for (String val : valArr){
            buildRdsTcp(strBuild, val);
        }

        return strBuild.toString();
    }

    public static StringBuffer buildRdsTcp(StringBuffer strBuild, String val){
        if (StringUtils.isBlank(val)){
            return strBuild;
        }

        strBuild.append("$").append(val.length()).append(CRLF).append(val).append(CRLF);

        return strBuild;
    }

    public static void request(SocketChannel socketChannel, String content) throws IOException {
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        buffer.put(content.getBytes());
        buffer.flip();
        socketChannel.write(buffer);
    }

    public static String response(SocketChannel socketChannel) throws IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        int len = 0;
        ByteBuffer buffer = ByteBuffer.allocate(1024);

        while (true) {
            buffer.clear();
            len = socketChannel.read(buffer);
            if (len == 0) break;
            buffer.flip();
            while (buffer.hasRemaining()) {
                bos.write(buffer.get());
            }
        }

        String ret = new String(bos.toByteArray());
        return ret;
    }

}
